package cn.org.xiaosheng.okhttp.utils;

import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * @author XiaoSheng
 * @date 2023-11-20
 * @dec 使用OkHttp作为Get请求的工具类底座
 */
@Component
@Slf4j
public class GetOkHttpUtils {

    @Resource
    private OkHttpClient okHttpClient;

    @Resource(name = "buildOkHttpClient")
    @Autowired
    private OkHttpClient buildOkHttpClient;

    /**
     * Get请求, 并提供header参数入参
     * 同步调用
     * @param url
     * @param headers
     * @param params
     * @return
     */
    public String getRequest(String url,
                             Map<String, String> headers,
                             Map<String, String> params) {
        if (params != null && !params.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            // 删除最后一个拼接符号&
            sb.deleteCharAt(sb.length() - 1);
            url = url + "?" + sb.toString();
        }
        Request.Builder reqBuild = new Request.Builder().url(url);
        //if (headers != null && !headers.isEmpty()) {
        //    for (int i = 0; i < headers.size(); i++) {
        //        reqBuild.addHeader(Objects.toString(headers.keySet().toArray()[i]),
        //                Objects.toString(headers.values().toArray()[i]));
        //    }
        //}
        // client.newCall(request)会返回一个Call对象，通过调用Call对象的execute方法就会执行同步请求，并返回一个Response对象
        // 对于同步调用，我们可以使用try代码块，编译器会帮我们在隐含的finally代码块中调用close方法。
        try (Response response = buildOkHttpClient.newCall(reqBuild.build()).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code: " + response);
            }
            // 打印响应体, 注意response.body().string() 调用一次之后Okio流将会关闭
            // OkHttpClient的返回值调用两次导致流已经关闭 会出现 java.lang.IllegalStateException: closed错误!
            String respData = response.body().string();
            System.out.println(respData);
            return respData;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Get请求, 并提供header参数入参
     * 异步调用
     * @param url
     * @param headers
     * @param params
     * @return
     */
    public String getRequestAsyn(String url,
                                 Map<String, String> headers,
                                 Map<String, String> params) {
        if (params != null && !params.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            // 删除最后一个拼接符号&
            sb.deleteCharAt(sb.length() - 1);
            url = url + "?" + sb.toString();
        }
        Request.Builder reqBuild = new Request.Builder().url(url);
        if (headers != null && !headers.isEmpty()) {
            for (int i = 0; i < headers.size(); i++) {
                reqBuild.addHeader(Objects.toString(headers.keySet().toArray()[i]),
                        Objects.toString(headers.values().toArray()[i]));
            }
        }
        // client.newCall(request)会返回一个Call对象，通过调用Call对象的execute方法就会执行同步请求，并返回一个Response对象
        // 对于异步调用
       okHttpClient.newCall(reqBuild.build()).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                // 非主线程
                e.printStackTrace();
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                try (ResponseBody responseBody = response.body()) {
                    if (!response.isSuccessful()) {
                        throw new IOException("Unexpected code " + response);
                    }
                    // 注意避坑! OkHttpClient的返回值调用两次导致流已经关闭 会出现 java.lang.IllegalStateException: closed错误!
                    System.out.println(responseBody.string());
                }
            }
        });
        return null;
    }

}
